package com.maple.common.utils

import android.content.ContentResolver
import android.content.Context
import android.database.Cursor
import android.graphics.Bitmap
import android.media.MediaMetadataRetriever
import android.net.Uri
import android.provider.MediaStore
import android.text.TextUtils
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileInputStream
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.util.Locale


/**
 * Tip: 文件
 * Create by SeVen on 2023/12/4 15:20
 */
object FileUtils {
    /**
     * string or FileInputStream to Byte[]
     * @param filePath 文件路径
     */
    @JvmStatic
    fun stringToByte(filePath: String): ByteArray? {
        var bos: ByteArrayOutputStream? = null
        var bis: BufferedInputStream? = null
        try {
            val file = File(filePath)
            if (!file.exists()) {
                throw FileNotFoundException("file not exists")
            }
            bos = ByteArrayOutputStream(file.length().toInt())
            bis = BufferedInputStream(FileInputStream(file))
            val size = 1024
            val buffer = ByteArray(size)
            var len: Int
            while (-1 != bis.read(buffer, 0, buffer.size).also { len = it }) {
                bos.write(buffer, 0, len)
            }
            return bos.toByteArray()
        } catch (e: Exception) {
            e.printStackTrace()
            return null
        } finally {
            try {
                bis?.close()
                bos?.close()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    /**
     * file to byte
     */
    @JvmStatic
    fun fileToByte(file: File): ByteArray? {
        var bos: ByteArrayOutputStream? = null
        var bis: BufferedInputStream? = null
        try {
            if (!file.exists()) {
                throw FileNotFoundException("file not exists")
            }
            bos = ByteArrayOutputStream(file.length().toInt())
            bis = BufferedInputStream(FileInputStream(file))
            val size = 1024
            val buffer = ByteArray(size)
            var len: Int
            while (-1 != bis.read(buffer, 0, buffer.size).also { len = it }) {
                bos.write(buffer, 0, len)
            }
            return bos.toByteArray()
        } catch (e: Exception) {
            e.printStackTrace()
            return null
        } finally {
            try {
                bis?.close()
                bos?.close()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    /**
     * 根据byte数组生成文件
     * @param byteArray 文件数组
     * @param filePath 文件存放路径
     * @param fileName 保存文件名称
     */
    @JvmStatic
    fun byteToFile(byteArray: ByteArray?, filePath: String, fileName: String): File? {
        var bos: BufferedOutputStream? = null
        var fos: FileOutputStream? = null
        try {
            val dir = File(filePath)
            if (!dir.exists() && !dir.isDirectory) {
                dir.mkdirs()
            }
            val file = File(filePath, fileName)
            fos = FileOutputStream(file)
            bos = BufferedOutputStream(fos)
            bos.write(byteArray)
            return file
        } catch (e: Exception) {
            e.printStackTrace()
            return null
        } finally {
            try {
                bos?.close()
                fos?.close()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    @JvmStatic
    fun getRealPathFromUri(context: Context, uri: Uri): String {
        var filePath = ""
        val scheme = uri.scheme
        if (scheme == null) {
            filePath = uri.path.toString()
        } else if (ContentResolver.SCHEME_FILE == scheme) {
            filePath = uri.path.toString()
        } else if (ContentResolver.SCHEME_CONTENT == scheme) {
            val proj = arrayOf(MediaStore.Images.Media.DATA)
            val cursor: Cursor? = context.contentResolver.query(
                uri, proj,
                null, null, null
            )
            cursor?.let {
                if (it.moveToFirst()) {
                    val columnIndex = it.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
                    filePath = it.getString(columnIndex)
                }
                it.close()
            }
            if (TextUtils.isEmpty(filePath)) {
                filePath = getFilePathForNonMedialUri(context, uri)
            }
        }
        return filePath
    }

    /**
     * 非媒体文件中查找
     */
    @JvmStatic
    private fun getFilePathForNonMedialUri(context: Context, uri: Uri): String {
        var filePath = ""
        val cursor: Cursor? = context.contentResolver.query(
            uri,
            null, null, null, null
        )
        cursor?.let {
            if (it.moveToFirst()) {
                val columIndex: Int = it.getColumnIndexOrThrow("_data")
                filePath = it.getString(columIndex)
            }
            it.close()
        }
        return filePath
    }

    /**
     * 文件名
     * @param prefix  前缀
     * @param suffix 后缀
     */
    @JvmStatic
    fun createFilePath(prefix: String, suffix: String): String {
        val sb = StringBuffer(255)
        sb.append(prefix)
        sb.append(System.currentTimeMillis())
        sb.append(suffix)
        return sb.toString()
    }

    fun getVideoThumbnail(context: Context, videoPath: String): Bitmap? {
        // 获取视频的ID
        val videoId = getVideoContentUri(context, videoPath)
        return MediaStore.Video.Thumbnails.getThumbnail(
            context.contentResolver,
            videoId!!,
            MediaStore.Video.Thumbnails.MINI_KIND,
            null
        )
    }

    private fun getVideoContentUri(context: Context, videoPath: String): Long? {
        val projection = arrayOf(MediaStore.Video.Media._ID)
        val selection = MediaStore.Video.Media.DATA + " = ?"
        val selectionArgs = arrayOf(videoPath)
        context.contentResolver.query(
            MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
            projection,
            selection,
            selectionArgs,
            null
        ).use { cursor ->
            if (cursor != null && cursor.moveToFirst()) {
                val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)
                return cursor.getLong(idColumn)
            }
        }
        return null
    }

    fun isVideoFile(filePath: String): Boolean {
        val retriever = MediaMetadataRetriever()
        return try {
            retriever.setDataSource(filePath)
            val metadata = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE)
            metadata != null && metadata.startsWith("video/")
        } catch (e: Exception) {
            false
        } finally {
            retriever.release()
        }
    }

    fun getVideoThumbnail(filePath: String): Bitmap? {
        val retriever = MediaMetadataRetriever()
        return try {
            retriever.setDataSource(filePath)
            retriever.getFrameAtTime(0, MediaMetadataRetriever.OPTION_CLOSEST_SYNC)
        } catch (e: IllegalArgumentException) {
            // 文件不是视频或路径无效
            null
        } finally {
            retriever.release()
        }
    }

    fun isVideoFile(file: File): Boolean {
        val name = file.name.lowercase(Locale.getDefault())
        return name.endsWith(".mp4") || name.endsWith(".mov") || name.endsWith(".m4v") || name.endsWith(
            ".3gp"
        ) || name.endsWith(".avi")
    }
}
